/*
 * @Author: daniel_du dll_2018@126.com
 * @Date: 2022-05-01 06:35:50
 * @LastEditors: daniel_du dll_2018@126.com
 * @LastEditTime: 2022-05-05 22:01:12
 * @FilePath: /safe_transmission_platform/src/client/ClientOption.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include "ClientOption.h"
#include "log.h"
#include "config.h"
#include "macro.h"
#include "codecFactory.h"
#include "codec.h"
#include "myrsa.h"
#include "myhash.h"
#include <fstream>
#include <sstream>
#include <openssl/rsa.h>
#include <openssl/pem.h>

static sylar::Logger::ptr g_logger=DANIEL_LOG_NAME("system");

ClientOption::ClientOption()
{
    //读取配置文件；主要包含客户端ID和服务端ID
    daniel::ConfigMsg::GetInstance()->loadFromFile("./client.yml");
    daniel::ConfigVar<ClientInfo>::ptr infoConfig=daniel::ConfigMsg::GetInstance()->lookUp<ClientInfo>("clientinfo");
    if (infoConfig==nullptr){
        DANIEL_LOG_DEBUG(g_logger)<<"get config failed!";
        DANIEL_ASSERT(false);
    }
    m_clientInfo=infoConfig->getValue();
}
ClientOption::~ClientOption()
{

}

void ClientOption::seckeyNego()
{
    daniel::MyRsa::ptr rsa(new daniel::MyRsa(daniel::MyRsa::GenerateKeys));
    rsa->generateKeys(1024);
    rsa->saveKeysToFile("./public.pem","./private.pem");
    std::fstream fs("./public.pem",std::ios::in);
    std::stringstream ss;
    std::string tmp;
    while (std::getline(fs,tmp)){
        ss<<tmp<<"\n";
        tmp.clear();
    }
    fs.close();
    std::string publicKey=ss.str();
    DANIEL_LOG_DEBUG(g_logger)<<"publicKey:"<<publicKey;
    // uint32_t siglen=0;
    std::string sigStr;
    std::string hashPublicKey;
    bool retHashsign=rsa->RSA_hashsign(daniel::MyRsa::SignSHA256,publicKey,hashPublicKey);
    DANIEL_ASSERT2(retHashsign,"hash sign failed!");
    DANIEL_LOG_DEBUG(g_logger)<<sigStr;
    daniel::RequestInfo resInfo;
    resInfo.cmd=SeckeyNego;
    resInfo.clientID=m_clientInfo.clientID;
    resInfo.serverID=m_clientInfo.serverID;
    resInfo.data=ss.str();
    resInfo.sign=hashPublicKey;
    //使用抽象工厂方法创建
    daniel::Factory::ptr factory(new daniel::RequestFactory(resInfo));
    daniel::Codec::ptr codec(factory->createObject());
    std::string msg=codec->encodeMsg();
    //将字符串发送给服务端，堵塞等待消息；
    m_socket.connectToHost(m_clientInfo.serverIP, m_clientInfo.serverPort);
    m_socket.sendMsg(msg);
    std::string respond;
    //保存对称加密的密钥
    m_socket.recvMsg(respond);
    DANIEL_LOG_DEBUG(g_logger)<<respond;
    RespondMsg respondMsg;
    respondMsg.ParseFromString(respond);
    if (respondMsg.rv()==true){
        // DANIEL_LOG_DEBUG(g_logger)<<"receive msg succeed;"<<std::endl;
        std::string randStr;
        //返回成功的消息
        rsa->privateDecrypt(respondMsg.data(),randStr);
        //需要解密，并且保存对称加密的密钥；
        DANIEL_LOG_DEBUG(g_logger)<<"AES Key:"<<randStr<<std::endl;
    }
}

void ClientOption::seckeyCheck()
{

}

void ClientOption::seckeyCancel()
{

}

struct ClientInfoInit
{
    ClientInfoInit()
    {
        daniel::ConfigMsg::GetInstance()->lookUp("clientinfo",ClientInfo(),"clientInfo");
    }  
};

static ClientInfoInit clientInfo;